﻿
using Dm.util;
using SqlSugar;
using YY.Admin.Core;
using YY.Admin.Core.SeedData;
using YY.Admin.Core.Session;
using YY.Admin.Core.Util;

namespace YY.Admin.Services.Service.User
{
    public class SysUserService : ISysUserService, ISingletonDependency
    {
        private readonly ISysOrgService _sysOrgService;
        private readonly ISqlSugarClient _dbContext;
        public SysUserService(ISysOrgService orgService, ISqlSugarClient dbContext)
        {
            _sysOrgService = orgService;
            _dbContext = dbContext;
        }

        public async Task<List<SysUser>> GetUsersAsync()
        {
            await Task.Delay(200);
            return new List<SysUser>();
        }

        public async Task<SqlSugarPagedList<UserOutput>> PageAsync(PageUserInput input)
        {
            var currentUser = AppSession.CurrentUser!;
            //获取子节点Id集合(包含自己)
            var orgList = await _sysOrgService.GetChildIdListWithSelfById(input.OrgId);
            return await _dbContext.Queryable<SysUser>()
                       .LeftJoin<SysOrg>((u, a) => u.OrgId == a.Id)
                       .LeftJoin<SysPos>((u, a, b) => u.PosId == b.Id)
                       .Where(u => u.AccountType != AccountTypeEnum.SuperAdmin)
                       //.Where(u => u.Status == StatusEnum.Enable)
                       .WhereIF(input.OrgId > 0, u => orgList.Contains(u.OrgId))
                       .WhereIF(!currentUser.IsSuperAdmin && !currentUser.IsSysAdmin, u => u.AccountType != AccountTypeEnum.SysAdmin)
                       .WhereIF(currentUser.IsSuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
                       .WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account.Contains(input.Account))
                       .WhereIF(!string.IsNullOrWhiteSpace(input.RealName), u => u.RealName.Contains(input.RealName))
                       .WhereIF(!string.IsNullOrWhiteSpace(input.NickName), u => u.NickName!.Contains(input.NickName))
                       .WhereIF(input.Sex.HasValue, u => u.Sex == input.Sex)
                       .WhereIF(!string.IsNullOrWhiteSpace(input.PosName), (u, a, b) => b.Name.Contains(input.PosName))
                       .WhereIF(!string.IsNullOrWhiteSpace(input.Phone), u => u.Phone!.Contains(input.Phone))
                       .WhereIF(input.Status.HasValue, u => u.Status == input.Status)
                       .WhereIF(input.BeginTime.HasValue, u => u.CreateTime >= input.BeginTime)
                       .WhereIF(input.EndTime.HasValue, u => u.CreateTime <= input.EndTime)
                       .OrderBy(u => SqlFunc.Desc(u.CreateTime))
                       .Select((u, a, b) => new UserOutput
                       {
                           OrgName = a.Name,
                           PosName = b.Name,
                           RoleName = SqlFunc.Subqueryable<SysUserRole>().LeftJoin<SysRole>((m, n) => m.RoleId == n.Id).Where(m => m.UserId == u.Id).SelectStringJoin((m, n) => n.Name, ","),
                           //DomainAccount = SqlFunc.Subqueryable<SysUserLdap>().Where(m => m.UserId == u.Id).Select(m => m.Account)
                       }, true)
                       .ToPagedListAsync(input.Page, input.PageSize);
        }

        public async Task<int> BatchDeleteAsync(List<long> ids)
        {
            int count = 0;
            if (ids == null || ids.isEmpty())
            {
                return count;
            }

            try
            {
                await _dbContext.AsTenant().BeginTranAsync();

                count = await _dbContext.Deleteable<SysUser>().In(ids).ExecuteCommandAsync();

                await _dbContext.AsTenant().CommitTranAsync();
            }
            catch (Exception)
            {
                await _dbContext.AsTenant().RollbackTranAsync();
            }

            return count;
        }

        public async Task<int> DeleteAsync(long id)
        {
            int count = 0;
            try
            {
                await _dbContext.AsTenant().BeginTranAsync();

                count = await _dbContext.Deleteable<SysUser>().In(id).ExecuteCommandAsync();

                await _dbContext.AsTenant().CommitTranAsync();
            }
            catch (Exception)
            {
                await _dbContext.AsTenant().RollbackTranAsync();
            }

            return count;
        }

        public async Task<int> CreateAsync(SysUser sysUser)
        {
            long maxId = await ReadMaxIdAsync();

            sysUser.Id = ++maxId;
            sysUser.Password = CryptogramUtil.Encrypt(sysUser.Password);
            sysUser.CardType = CardTypeEnum.IdCard;
            sysUser.CultureLevel = CultureLevelEnum.Level0;
            sysUser.PosId = new SysPosSeedData().HasData().ToList()[0].Id;
            sysUser.TenantId = SqlSugarConst.DefaultTenantId;
            sysUser.CreateTime = DateTime.Now;
            sysUser.CreateUserId = AppSession.UserId;
            sysUser.CreateUserName = AppSession.CurrentUser!.Account;

            int count = 0;
            try
            {
                await _dbContext.AsTenant().BeginTranAsync();

                count = await _dbContext.Insertable(sysUser).ExecuteCommandAsync();

                await _dbContext.AsTenant().CommitTranAsync();
            }
            catch (Exception)
            {
                await _dbContext.AsTenant().RollbackTranAsync();
            }

            return count;
        }

        public async Task<int> UpdateAsync(SysUser sysUser)
        {
            sysUser.UpdateUserId = AppSession.UserId; ;
            sysUser.UpdateUserName = AppSession.CurrentUser!.Account;
            sysUser.UpdateTime = DateTime.Now;

            int count = 0;
            try
            {
                await _dbContext.AsTenant().BeginTranAsync();

                count = await _dbContext.Updateable(sysUser)
                    .UpdateColumns(it => new { it.RealName, it.NickName, it.Sex, it.Birthday, it.Age, it.Status, it.UpdateUserId, it.UpdateUserName, it.UpdateTime })
                    .ExecuteCommandAsync();

                await _dbContext.AsTenant().CommitTranAsync();
            }
            catch (Exception)
            {
                await _dbContext.AsTenant().RollbackTranAsync();
            }

            return count;
        }

        public async Task<long> ReadMaxIdAsync()
        {
            return await _dbContext.Queryable<SysUser>().MaxAsync<long>("Id");
        }

        public async Task<bool> AccountExistsAsync(string account, long? excludeUserId)
        {
            var query = _dbContext.Queryable<SysUser>()
        .   Where(u => u.Account == account);

            // excludeUserId不等于null && 不等于 0
            if (excludeUserId.HasValue && excludeUserId != 0)
            {
                query = query.Where(u => u.Id != excludeUserId.Value);
            }

            return await query.AnyAsync();
        }

        public async Task<int> ToggleStatus(SysUser sysUser)
        {
            sysUser.UpdateUserId = AppSession.UserId; ;
            sysUser.UpdateUserName = AppSession.CurrentUser!.Account;
            sysUser.UpdateTime = DateTime.Now;

            int count = 0;
            try
            {
                await _dbContext.AsTenant().BeginTranAsync();

                count = await _dbContext.Updateable(sysUser)
                    .UpdateColumns(it => new { it.Status, it.UpdateUserId, it.UpdateUserName, it.UpdateTime })
                    .ExecuteCommandAsync();

                await _dbContext.AsTenant().CommitTranAsync();
            }
            catch (Exception)
            {
                await _dbContext.AsTenant().RollbackTranAsync();
            }

            return count;
        }
    }
}
